/*
 * Copyright (c) 2008 Sergey Rudchenko <sergey.rudchenko@gmail.com>
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "game.h"
#include "image_pool.h"
#include "scene.h"

#include <stdlib.h>

struct game* new_game()
{
    struct game* obj = malloc(sizeof(struct game));
    obj->screen  = NULL;
    obj->vid_fps = 24;
    obj->scenes  = NULL;
    obj->global_data = NULL;
    obj->_ticks = SDL_GetTicks();
    return obj;
}

void free_game(struct game* obj)
{
    game_vid_shutdown(obj);
    free(obj);
}

int game_vid_init(struct game* ctx)
{
    ctx->screen = SDL_SetVideoMode(ctx->vid_resx,
                                   ctx->vid_resy,
                                   ctx->vid_bpp,
                                   SDL_HWSURFACE | SDL_DOUBLEBUF);

    if (!ctx->screen)
    {
        printf("Failed to set videomode: %ux%u %u bit: %s",
               ctx->vid_resx, ctx->vid_resy, ctx->vid_bpp,
               SDL_GetError());
        return 1;
    }

    SDL_WM_SetCaption("Relaxian", NULL);
    SDL_ShowCursor(SDL_DISABLE);

    ctx->area.x = ctx->area.y = 0;
    ctx->area.w = ctx->screen->w;
    ctx->area.h = ctx->screen->h;

    if (ctx->vid_fps == 0)
        ctx->vid_fps = 24;
    ctx->_frame_delay = 1000 / ctx->vid_fps;

    return load_images();
}

void game_vid_shutdown(struct game* ctx)
{
    if (ctx->screen)
    {
        SDL_FreeSurface(ctx->screen);
        ctx->screen = NULL;
        unload_images();
    }
}

static void game_sync_frame(struct game* ctx)
{
    SDL_Flip(ctx->screen);
    //SDL_Delay(ctx->_frame_delay);
}

static void game_global_hooks(struct game* ctx)
{
    SDL_Event event;
    while (SDL_PollEvent(&event))
    {
        if (event.type == SDL_KEYDOWN &&
            event.key.keysym.sym == SDLK_RETURN &&
            event.key.keysym.mod & KMOD_ALT)
        {
            SDL_WM_ToggleFullScreen(ctx->screen);
        }
    }
}

void game_push_scene(struct game* ctx, struct scene* scene)
{
    ctx->scenes = g_slist_append(ctx->scenes, scene);
}

void game_run(struct game* ctx)
{
    while (ctx->scenes)
    {
        struct scene* scene = ctx->scenes->data;
        ctx->scenes = g_slist_delete_link(ctx->scenes, ctx->scenes);

        int scene_alive = 0;
        do
        {
            game_global_hooks(ctx);

            Uint32 ticks = SDL_GetTicks();
            scene_alive = scene->update(scene, ctx, ticks - ctx->_ticks);
            ctx->_ticks = ticks;

            game_sync_frame(ctx);
        } while (scene_alive);

        free_scene(scene);
    }
}

